#include "main.h"
#pragma execution_character_set("utf-8")
Stack_Qstr showUI;
#define maxusernumber 99
typedef struct
{
    uint8_t last_h;
    uint8_t worktime;
} uWork;
uWork finger_record[maxusernumber][33]; //[userID][day]
void uiprint(QTESPMAIN_926 *w, string ss)
{
    try
    {
        QTextCursor cursor = w->ui.textEdit->textCursor();
        cursor.movePosition(QTextCursor::End);
        w->ui.textEdit->setTextCursor(cursor);
        w->ui.textEdit->insertPlainText(QString::fromStdString(ss));
        w->ui.textEdit->insertPlainText(" \n");
    }
    catch (const std::exception &)
    {
        printf("Printf Error");
    }
}

char recv_buf[100];
char send_buf[1024];
u8 dataframe[1024];
uint8_t RXCommandBuffe[8];
uint8_t TXCommandBuffe[8];
u8 command[3];
int aaa = 0;
int responddataNum = 0;
u8 hearFlag = 0;
u8 ResPoundFlag = 0;
StopWatch hearTime;
int userID[99][2];
u8 getWorkDataFlag = 0;
u8 getCheck(u8 *txcmd)
{
    u8 res = 0;
    for (uint8_t i = 0; i < 7; i++)
    {
        //  printf("tx %d txI %d \n", txcmd[i] % 10, res);
        res += (txcmd[i] % 10);
    }
    return res;
}
void build_cmd(u8 *data, u8 tid, u8 Cmd, u16 datalen)
{
    data[0] = 0xAF;
    data[1] = 0xFA;
    data[2] = 5;   // 本机
    data[3] = tid; // 目标
    data[4] = Cmd; // 指令
    data[5] = (datalen >> 8);
    data[6] = datalen & 0xff;
    data[7] = getCheck(data);
}
// ocket
SOCKET serverSocket;
string cIP = "0";
int connectIP(string ip)
{
   // string beginIP = util::Format("192.168.{0}.179", ip);
    SOCKET TempserverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    int res;
    SOCKADDR_IN sAddr = {0};
    sAddr.sin_family = AF_INET;
    sAddr.sin_addr.S_un.S_addr = inet_addr(ip.c_str()); // 设置IP
    sAddr.sin_port = htons(8080);                            // 设置端口
    // 4.���ӷ�����
    res = connect(TempserverSocket, (SOCKADDR *)&sAddr, sizeof(sAddr));

    if (res != -1)
    {
        cIP = ip;
        printf("find OK \n\n\n");
        serverSocket = TempserverSocket;
        printf(ip.c_str());
    }
    return res;
}

void AUTOconnectWork() {
    string ipp;
    ThreadPool pool(255);

    connectIP("192.168.234.179");
    return;
    for (int p1 = 234; p1 < 255; p1++) {

        showUI.push(("\n AUTO :: begin connect IP :" + util::Format("192.168.{0}.0}", p1) + " to " + util::Format("192.168.{0}.255}", p1) + '\n'));
        for (int p = 0; p < 255; p++)
        {
            if (pool.tasksisFull()) {
                showUI.push("\nAUTO connect Thread Waiting \n");
                while (!pool.tasksisempty()) {
                    if (cIP.size() != 0 && cIP[0] != '0')
                    {
                        showUI.push("\nAUTO connect Thread RunOFF \n");
                        return;
                    }
                };
            };
            if (cIP.size() != 0 && cIP[0] != '0')
            {
                showUI.push("\nAUTO connect Thread RunOFF \n");
                return;
            }
            ipp = util::Format("192.168.{0}.{1}", p1, p);
            string prin = "connect " + ipp + '\n';
            printf(prin.c_str());
            pool.enqueue(connectIP, ipp); // 创建自动连接线程
        }
    }
}
void saveInCsv();
u8 tcp_loop;
void TcpMeg(QTESPMAIN_926 *w)
{
    aaa = 1;
    showUI.push("TCP OPen");
    WORD wVersionRequested;
    WSADATA wsaData;

    int err;
    wVersionRequested = MAKEWORD(2, 2);
    err = WSAStartup(wVersionRequested, &wsaData);

    if (err != 0)
    {
        printf("error1");
        return;
    }
    if (LOBYTE(wsaData.wVersion) != 2 ||
        HIBYTE(wsaData.wVersion) != 2)
    {
        WSACleanup();
        printf("error2");
        return;
    }
    showUI.push("wVersionRequested succeed");
    serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (SOCKET_ERROR == serverSocket)
    {
        WSACleanup();
        printf("error3");
        return;
    }
    showUI.push("serverSocket>>socket success");
    showUI.push("begin AUTO connect ");
    // 3.ȷ��������Э���ַ��
    
    {
        SOCKET TempserverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        int res;
        SOCKADDR_IN sAddr = { 0 };
        sAddr.sin_family = AF_INET;
        string ip = w->ui.LineIP->text().toStdString();
        sAddr.sin_addr.S_un.S_addr = inet_addr(ip.c_str()); // 设置IP
        sAddr.sin_port = htons(8080);                            // 设置端口
        // 4.���ӷ�����
        res = connect(TempserverSocket, (SOCKADDR*)&sAddr, sizeof(sAddr));

        if (res != -1)
        {
            cIP = ip;
            printf("find OK \n\n\n");
            serverSocket = TempserverSocket;
            printf(ip.c_str());
        }
    }

    showUI.push("\nAUTO connect Thread Runing \n");
    if (cIP[0] == '0')
    {
        showUI.push("AUTO connect failure");
        return;
    }

    showUI.push(("AUTO connect IP Scueed :" + cIP + '\n'));
    showUI.push("socket>>connect succeed");
    BYTE TXCommandBuffe[8];
    TXCommandBuffe[0] = 0xAF;
    TXCommandBuffe[1] = 0xFA;
    TXCommandBuffe[2] = 5; // 本机ID
    TXCommandBuffe[3] = 1; // 目标ID
    TXCommandBuffe[4] = 0; // 指令 心跳
    TXCommandBuffe[5] = 0;
    TXCommandBuffe[6] = 0;
    TXCommandBuffe[7] = 0;
    vector<BYTE> A;
    for (uint8_t i = 0; i < 7; i++)
    {
        // printf("tx7 %d txI %d \n", TXCommandBuffe[7], TXCommandBuffe[i] % 10);
        TXCommandBuffe[7] += (TXCommandBuffe[i] % 10);
    }

    try
    {
        send(serverSocket, (char *)TXCommandBuffe, sizeof(TXCommandBuffe), NULL);
    }
    catch (const std::exception &)
    {
        printf("Send Error");
    }

    int datalen = 0;
    responddataNum = 0;
    u8 errorout = 0;
    while (tcp_loop>0)
    {
        if (datalen == 0)
        {
            int recv_len = recv(serverSocket, (char *)RXCommandBuffe, 8, 0);
            if (recv_len < 0)
            {
                // printf("Recv Error");
            }
            else
            {
                // for (u8 i = 0; i < 8; i++)
                //     printf("%d ", RXCommandBuffe[i]);

                if (RXCommandBuffe[0] == 0XAF && RXCommandBuffe[1] == 0XFA && check_RXcommand())
                {
                    command[0] = RXCommandBuffe[2];
                    command[1] = RXCommandBuffe[3];
                    command[2] = RXCommandBuffe[4];
                    datalen = (RXCommandBuffe[5] << 8) | RXCommandBuffe[6];
                    if (command[2] == Cmd_Heartbea)
                    {
                        if (hearFlag)
                            hearFlag = 0;
                        else
                            hearFlag = 1;
                        w->ui.Radio_Bit->setChecked(hearFlag);
                    }
                    else if (command[2] == Cmd_ResPound)
                    {
                        responddataNum++;
                        w->ui.lcdNumber->display(responddataNum);
                        ResPoundFlag = 1;
                        showUI.push("Get Cmd_ResPound");
                    }
                    else
                    {
                        showUI.push("get command");
                        printf("\n\n get command id %d len %d\n", command[1], datalen);
                    }
                    if (datalen > 0)
                    {
                        build_cmd(TXCommandBuffe, 1, 0xB1, 0); // Ӧ��
                        send(serverSocket, (char *)TXCommandBuffe, sizeof(TXCommandBuffe), NULL);
                        printf("send respound\n");
                        errorout = 0;
                    }
                }
                else if (RXCommandBuffe[0] == 0XDF && RXCommandBuffe[1] == 0XFD)
                {
                    build_cmd(TXCommandBuffe, 1, 0xB1, 0); // Ӧ��
                    send(serverSocket, (char *)TXCommandBuffe, sizeof(TXCommandBuffe), NULL);
                }
            }
        }
        else
        {
            errorout++;
            if (errorout > 3)
            {
                showUI.push("Get dataFrame Error Retry");
                datalen = 0;
                errorout = 0;
            }

            showUI.push("Get dataFrame");
            int recv_len = recv(serverSocket, (char *)dataframe, datalen, 0);
            if (recv_len < 0)
            {
                printf("RECV Error");
            }
            else
            {
                static u8 verifyCode = 0, indx = 0, workday = 1;
                u16 dataindex = 2;
                printf("\n\nd1 %d d2 %d \n", dataframe[0], dataframe[1]);
                if (dataframe[0] == 0XDF && dataframe[1] == 0XFD)
                {
                    printf("begin get data \n");
                    showUI.push("begin get data");
                    for (; indx < maxusernumber; indx++)
                    {

                        for (; workday < 32; workday++)
                        { // 31
                            if (dataindex >= datalen)
                                break;
                            finger_record[indx][workday].worktime = dataframe[dataindex];
                            // printf("data %d\t", dataframe[dataindex]);
                            verifyCode += dataframe[dataindex] % 10;

                            dataindex++;
                        }
                        if (dataindex >= datalen)
                            break;
                        workday = 1;
                    }
                    build_cmd(TXCommandBuffe, 1, 0xB1, 0); // Ӧ��
                    send(serverSocket, (char *)TXCommandBuffe, sizeof(TXCommandBuffe), NULL);
                    datalen = 0;
                }

                if (dataframe[0] == 0XBA && dataframe[1] == 0XAB)
                {
                    showUI.push("begin get finish data");
                    printf("begin get finish data \n");
                    for (; indx < maxusernumber; indx++)
                    {

                        for (; workday < 32; workday++)
                        { // 31
                            if (dataindex >= datalen - 1)
                                break;

                            finger_record[indx][workday].worktime = dataframe[dataindex];
                            printf("data %d\t", dataframe[dataindex]);
                            verifyCode += dataframe[dataindex] % 10;

                            dataindex++;
                        }
                        if (dataindex >= datalen - 1)
                            break;
                        workday = 1;
                    }
                    for (u8 ii = 0; ii < datalen; ii++)
                    {
                        printf("%d \t", dataframe[ii]);
                    }
                    build_cmd(TXCommandBuffe, 1, 0xB1, 0); // Ӧ��
                    send(serverSocket, (char *)TXCommandBuffe, sizeof(TXCommandBuffe), NULL);
                    printf("\n\n data recvFinish check %d dada check %d \n\n", verifyCode, dataframe[datalen - 1]);
                    showUI.push("\n\n\n\nGet Data OK\n\n\n\n");
                    verifyCode = 0;
                    indx = 0;
                    workday = 1;
                    datalen = 0;
                    getWorkDataFlag = 1;
                    saveInCsv();
                    
                }
            }
            // else if (recv_len == 8)
            // {
            //     if (dataframe[0] == 0XAF && dataframe[1] == 0XFA)
            //     {
            //         dataframe[0] = 0;
            //         dataframe[1] = 0;
            //         build_cmd(TXCommandBuffe, 1, 0xB1, 0); // Ӧ��
            //         send(serverSocket, (char *)TXCommandBuffe, sizeof(TXCommandBuffe), NULL);
            //         printf("send respound");
            //     }
            // }
        }
    }
}

StopWatch IDTime;
void SendUserID()
{
    showUI.push("Begin Send UserID \n\n\n\n");
    BYTE sendbuf[1024];
    uint16_t idwz = 0;
    u16 len = 0;
    u8 verifyCode = 0;
    printf("\n\n\n");
    for (uint8_t i = 0; i < 99; i++)
    {
        for (uint8_t m = 0; m < 2; m++)
        {
            printf("\n%d :", userID[i][m]);
            for (uint8_t n = 0; n < 4; n++)
            {
                sendbuf[idwz] = ((userID[i][m] >> (8 * n)) & (0xff));
                printf("%d ", sendbuf[idwz]);
                verifyCode += sendbuf[idwz] % 10;
                idwz++;
                len++;
            }
        }
    }
    printf("\n\n\n");
    int iii = 0;
    for (uint8_t i = 0; i < 99; i++)
    {
        for (uint8_t m = 0; m < 2; m++)
        {
            int data = 0;
            for (uint8_t n = 0; n < 4; n++)
            {
                data |= sendbuf[iii] << (8 * n);
                iii++;
            }
            printf("%d \t", data);
        }
    }
    sendbuf[len] = verifyCode;
    len++;
    printf("data len %d verifyCode %d ", len, verifyCode);
    showUI.push("Begin Send Command");
    BYTE TXCommandBuffe[8];
    TXCommandBuffe[0] = 0xAF;
    TXCommandBuffe[1] = 0xFA;
    TXCommandBuffe[2] = 5;
    TXCommandBuffe[3] = 1;
    TXCommandBuffe[4] = 0xA1;
    TXCommandBuffe[5] = ((len >> 8) & (0xff));
    TXCommandBuffe[6] = (len & 0xff);
    TXCommandBuffe[7] = 0;
    printf("len %d len1 %d len2 %d", len, TXCommandBuffe[5], TXCommandBuffe[6]);
    for (uint8_t i = 0; i < 7; i++)
    {
        // printf("tx7 %d txI %d \n", TXCommandBuffe[7], TXCommandBuffe[i] % 10);
        TXCommandBuffe[7] += (TXCommandBuffe[i] % 10);
    }

    send(serverSocket, (char *)TXCommandBuffe, sizeof(TXCommandBuffe), NULL);
    IDTime.tic();
    //showUI.push("Send Suceed");
    while (!ResPoundFlag)
    {
        if (IDTime.toc() > 3000)
            break;
    }
    ResPoundFlag = 0;
    send(serverSocket, (char *)sendbuf, len, NULL);
    printf("\n\n\nSend OK!!!!\n\n\n");

}

void get_userWorkTime()
{
    showUI.push("Begin Send GetWorkTime Cmd");
    BYTE TXCommandBuffe[8];
    TXCommandBuffe[0] = 0xAF;
    TXCommandBuffe[1] = 0xFA;
    TXCommandBuffe[2] = 5;
    TXCommandBuffe[3] = 1;
    TXCommandBuffe[4] = 0xA2;
    TXCommandBuffe[5] = 0;
    TXCommandBuffe[6] = 0;
    TXCommandBuffe[7] = getCheck(TXCommandBuffe);
    send(serverSocket, (char *)TXCommandBuffe, 8, NULL);
}

StopWatch UITime;
StopWatch UITime2;
void UiUpdata(QTESPMAIN_926 *w)
{
    u8 uiupFlag = 0;
    UITime.tic();
    UITime2.tic();
    while (true)
    {
        if (showUI.size() > 0 && UITime2 .toc() > 250)
        {
            UITime2.tic();
            uiprint(w, showUI.top());
        }
        else // 打印完日志再处理
        {
            if (uiupFlag)
            {
                if (cIP[0] != '0')
                    w->ui.LineIP->setText(QString::fromStdString(cIP));
                uiupFlag = 0;
            }
            if (UITime.toc() > 1000)
            {
                uiupFlag = 1;
                UITime.tic();
            }
        }
    }
}
int StrToInt(string ss, bool mod)
{
    if (!mod)
    {
        int res = 0;
        for (u8 i = 0; i < 5; i++)
        {
            res *= 10;
            res += (ss[i] - '0');
        }
        // printf("%d ", res);
        return res;
    }
    else
    {
        int res = 0;
        for (u8 i = 5; i < 10; i++)
        {
            res *= 10;
            res += (ss[i] - '0');
        }
        //   printf("%d ", res);
        return res;
    }
}
void PrintCSVLine(vector<string> line_data)
{

    for (string str : line_data)
    {
        cout << str << " ";
    }
    cout << endl;
}
void readCsv()
{
    string fname = "user.csv";
    showUI.push("Begin Read Csv");
    // �Զ��뷽ʽ���ļ�
    ifstream csv_data(fname, ios::in);

    if (!csv_data.is_open())
    {
        cout << "Error: opening file fail" << endl;
        exit(1);
    }

    else
    {
        string line;

        vector<string> words; // ����һ���ַ�������
        string word;
        // 读取标题
        getline(csv_data, line);

        // printf("%s \n",line);
        istringstream sin;
        u8 indx = 0;
        // 读取每一行
        while (getline(csv_data, line))
        {
            // 清空
            words.clear();
            sin.clear();

            sin.str(line);
            // 读取每一行数据进入 sin 并以，分隔输入word
            while (getline(sin, word, ','))
            {
                // cout << word << endl;
                words.push_back(word);
            }
            userID[indx][0] = StrToInt(words[2], 0);
            userID[indx][1] = StrToInt(words[2], 1);
            printf("%d %d \n", userID[indx][0], userID[indx][1]);
            indx++;
        }

        csv_data.close();
    }
    showUI.push("Read Csv Suceed");
}

void saveInCsv()
{
    if (!getWorkDataFlag)
    {
        showUI.push("Have No Data to Save");
        return;
    }
    showUI.push("\n\nBegin save CSV\n\n");
    string fname0 = "user.csv";

    ifstream csv_data(fname0, ios::in);
    string topline;
    if (csv_data.is_open())
    {
        getline(csv_data, topline);
    }
    csv_data.close();
    string fname = "user.csv";

    ofstream csv_Savedata(fname, ios::out);
    int wmax = 0, wmin = 1000, wavg = 0;
    if (csv_Savedata.is_open())
    {
        csv_Savedata << topline << endl;
        for (int i = 0; i < maxusernumber; i++)
        {
            wmax = 0, wmin = 1000, wavg = 0;
            csv_Savedata << i << ',' << " " << ',' << to_string(userID[i][0]) << to_string(userID[i][1]) << ',';
            for (int day = 1; day < 32; day++)
            {
                csv_Savedata << to_string(finger_record[i][day].worktime) << ',';
                wmax = max(wmax, finger_record[i][day].worktime);
                wmin = min(wmin, finger_record[i][day].worktime);
                wavg += finger_record[i][day].worktime;
                printf("%d \t", finger_record[i][day].worktime);
            }
            wavg /= 31;
            csv_Savedata << wavg << ',' << wmax << ',' << wmin << ',';
            csv_Savedata << endl;
        }
    }
    csv_Savedata.close();
    printf("save ok");
    showUI.push("\nData save at user2.csv\n");
}
//10.33.58.225
int main(int argc, char *argv[])
{

    QApplication a(argc, argv);
    QTESPMAIN_926 w;
    thread UiUpdata_thread;
    UiUpdata_thread = thread(UiUpdata, &w);
    w.ui.LineIP->setText(QString::fromStdString("0.0.0.0"));
    readCsv();
    thread TcpMeg_thread;
    tcp_loop = 1;
    QObject::connect(w.ui.BU_connect, &QPushButton::clicked,
                     [&]()
                     {
                         if (tcp_loop==1) {
                             TcpMeg_thread = thread(TcpMeg, &w);
                             tcp_loop = 2;
                         }else {
                              tcp_loop = 0;
                              TcpMeg_thread.join();}
               
                     });

    QObject::connect(w.ui.BU_PostUserID, &QPushButton::clicked,
                     [&]()
                     {
                        thread TcpMeg_send;
                        TcpMeg_send = thread(SendUserID);
                        TcpMeg_send.join();
                     });
    QObject::connect(w.ui.BU_Get_UserData, &QPushButton::clicked,
                     [&]()
                     {
                         get_userWorkTime();
                     });

    w.show();
    return a.exec();
}
//10.33.96.127
void Stack_Qstr::push(string value)
{
    data.push_back(value);
}

void Stack_Qstr::pop()
{
    if (!data.empty())
    {
        data.erase(data.begin() + 0);
    }
}

string Stack_Qstr::top()
{
    string res;
    if (!data.empty())
    {
        res = data[0];
        pop();
        return res;
    }
    res = "\n";
    return res;
}

uint8_t Stack_Qstr::size()
{
    return data.size();
}

u8 check_RXcommand()
{
    u8 check = 0;
    for (u8 i = 0; i < 7; i++)
        check += RXCommandBuffe[i] % 10;
    // printf("check : %d  RXcheck : %d\n", check, RXCommandBuffe[7]);
    return (check == RXCommandBuffe[7]);
}

int gettimeofday(struct timeval *tp, void *tzp)
{
    time_t clock;
    struct tm tm;
    SYSTEMTIME wtm;
    GetLocalTime(&wtm);
    tm.tm_year = wtm.wYear - 1900;
    tm.tm_mon = wtm.wMonth - 1;
    tm.tm_mday = wtm.wDay;
    tm.tm_hour = wtm.wHour;
    tm.tm_min = wtm.wMinute;
    tm.tm_sec = wtm.wSecond;
    tm.tm_isdst = -1;
    clock = mktime(&tm);
    tp->tv_sec = clock;
    tp->tv_usec = wtm.wMilliseconds * 1000;
    return (0);
}
